﻿using GComp.Apps.EasyStock.DataModel.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace GComp.Apps.EasyStock.Controls {
    public sealed partial class HistoryDiagram : UserControl {
        public HistoryDiagram() {
            this.InitializeComponent();
            dias.Add(this);
        }

        static List<HistoryDiagram> dias = new List<HistoryDiagram>();
        private int dataForLastDays = 7;
        private List<TextBlock> textblocks = new List<TextBlock>();

        public string Symbol {
            get { return (string)GetValue(SymbolProperty); }
            set { SetValue(SymbolProperty, value); LoadData(); }
        }

        public static readonly DependencyProperty SymbolProperty =
            DependencyProperty.Register("Symbol", typeof(string), typeof(HistoryDiagram),
            new PropertyMetadata("", new PropertyChangedCallback(OnSymbolChanged)));

        private static void OnSymbolChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            HistoryDiagram hc = d as HistoryDiagram;
            if (hc != null)
                hc.LoadData();
        }

        public List<Tuple<DateTime, decimal>> Values {
            get { return (List<Tuple<DateTime, decimal>>)GetValue(ValuesProperty); }
            set { SetValue(ValuesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Values.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValuesProperty =
            DependencyProperty.Register("Values", typeof(List<Tuple<DateTime, decimal>>), typeof(HistoryDiagram),
            new PropertyMetadata(new List<Tuple<DateTime, decimal>>(), new PropertyChangedCallback(OnValuesChanged)));

        private static void OnValuesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            HistoryDiagram hc = d as HistoryDiagram;
            if (hc != null)
                hc.RecalcChart();
        }

        public async void LoadData() {
            HistoryQuery query = new HistoryQuery(Symbol, DateTime.Today.AddDays(-dataForLastDays - 2), DateTime.Today);
            Values = await query.GetAnswerAsync();
            Debug.WriteLine("successfully loaded " + Symbol + " with " + Values.Count + " values");
        }

        // Umrechnen der in Values gespeicherten Daten und Kurse in Koordinaten zum Zeichnen.
        // Das Zielrechteck berechnet sich nicht aus der Größe des Controls selbst, sondern aus den
        // (in der XAML.Datei festgelegten) Koordinaten der Achsen. Die müssen dazu in die richtige
        // Richtung zeigen und können in einer abgeleiteten Klasse, z. B. für eine Detail-Seite, einen
        // größeren Rand mit Beschriftungen definieren.
        private void RecalcChart() {
            InitAxes();

            foreach (TextBlock tb in textblocks) {
                canvas.Children.Remove(tb);
            }
            textblocks.Clear();

            if (Values == null || Values.Count == 0) {
                this.curve.Points = new PointCollection();
                this.tbNoValues.Visibility = Windows.UI.Xaml.Visibility.Visible;
                return;
            }
            this.tbNoValues.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

            double minVal = (double)Values.Min(v => v.Item2);
            double maxVal = (double)Values.Max(v => v.Item2);
            if (maxVal == minVal)
                maxVal = minVal + 10;
            DateTime dtStart = Values.First().Item1;
            DateTime dtEnd = Values.Last().Item1;
            if (dtEnd == dtStart)
                dtStart = dtEnd - TimeSpan.FromDays(1);
            double width = xAxis.X2 - xAxis.X1;
            double height = yAxis.Y2 - yAxis.Y1;
            double pixelsPerTick = width / (dtEnd.Ticks - dtStart.Ticks);
            double pixelsPerDollar = height / (maxVal - minVal);
            PointCollection points = new PointCollection();
            foreach (var record in Values) {
                double x = xAxis.X1 + (record.Item1.Ticks - dtStart.Ticks) * pixelsPerTick;
                double y = yAxis.Y2 - (yAxis.Y1 + (((double)record.Item2) - minVal) * pixelsPerDollar);
                points.Add(new Point(x, y));

                if (Values.Count < 50) {
                    TextBlock tb = new TextBlock {
                        Text = Math.Round(record.Item2, 2).ToString(),
                        Foreground = new SolidColorBrush(Colors.Black)
                    };
                    canvas.Children.Add(tb);
                    Canvas.SetLeft(tb, x - 5);
                    Canvas.SetTop(tb, y - 15);
                    textblocks.Add(tb);
                }
            }
            curve.Points = points;

            xAxis.Visibility = Visibility.Visible;
            yAxis.Visibility = Visibility.Visible;
            curve.Visibility = Visibility.Visible;
            tbMax.Text = maxVal.ToString();
            tbMin.Text = minVal.ToString();
        }

        private void InitAxes() {
            xAxis.X1 = 0;
            xAxis.X2 = canvas.ActualWidth;
            xAxis.Y1 = canvas.ActualHeight;
            xAxis.Y2 = canvas.ActualHeight;

            yAxis.Y1 = 0;
            yAxis.Y2 = canvas.ActualHeight;
            yAxis.X1 = 0;
            yAxis.X2 = 0;
        }

        private void OnRadioButtonChecked(object sender, RoutedEventArgs e) {
            switch ((sender as RadioButton).Name) {
                case "rbLastWeek": dataForLastDays = 7; break;
                case "rbLastMonth": dataForLastDays = 31; break;
                case "rbLast3Months": dataForLastDays = 31 * 3; break;
                case "rbLastYear": dataForLastDays = 365; break;
                case "rbLast3Years": dataForLastDays = 365 * 3; break;
            }

            LoadData();
        }
    }
}
